package edu.fsu.cs.contextprovider.sensor;
import android.app.Service;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.SharedPreferences;
import android.content.SharedPreferences.OnSharedPreferenceChangeListener;
import android.location.Location;
import android.location.LocationListener;
import android.location.LocationManager;
import android.location.LocationProvider;
import android.os.Bundle;
import android.os.IBinder;
import android.preference.PreferenceManager;
import android.speech.tts.TextToSpeech;
import android.util.Log;
import android.widget.Toast;
import edu.fsu.cs.contextprovider.ContextExpandableListActivity;
import edu.fsu.cs.contextprovider.data.ContextConstants;
/**
* Most objects are declared static because we want only 1 instance. We could have instead used an iBinder but it is a bit
* of overkill for this situation.
* @author meyers
*
*/
public class GPSService extends Service implements OnSharedPreferenceChangeListener
{
private static final String TAG = "GPSService";
private static final boolean DEBUG_TTS = false;
private static final boolean DEBUG = false;
private SharedPreferences prefs;
private static final String locationType = LocationManager.GPS_PROVIDER;
private static LocationManager manager;
private static LocationListener listener;
private static boolean running = false;
private static boolean isreliable = false;
private static Location currentLocation = new Location(locationType);
@Override
public IBinder onBind(Intent intent) {
return null;
}
/** method for clients */
public static double getLatitude() {
return currentLocation.getLatitude();
}
public static double getLongitude() {
return currentLocation.getLongitude();
}
public static float getSpeed() {
if (currentLocation == null) {
return 0;
}
return currentLocation.getSpeed();
}
public static double getAltitude() {
return currentLocation.getAltitude();
}
/* TODO: Maybe convert this to N, S, E, or W */
public static float getBearing() {
return currentLocation.getBearing();
}
public static Location getLocation() {
return currentLocation;
}
/**
* Often times the GPS goes in and out of service. We perform some logic to determine
* if the current GPS reading is reliable or not.
*
* @return
*/
public static boolean isReliable() {
return isreliable;
}
public void onCreate() {
startService();
}
public void startService() {
getPrefs();
listener = new LocationListener() {
public void onLocationChanged(Location location) {
isreliable = true;
currentLocation.set(location);
if (DEBUG) {
Log.i(TAG, "New location found: [" + location.getLongitude() + "," + location.getLatitude() + "] | Speed: [" + location.getSpeed() + "]");
}
}
public void onProviderDisabled(String provider) {
//manager.removeUpdates(this);
if (DEBUG) {
Log.i(TAG, locationType + ": is no longer reliable");
}
isreliable = false;
if (DEBUG_TTS) {
ContextExpandableListActivity.tts.speak("GPS reliability is " + String.valueOf(isreliable), TextToSpeech.QUEUE_FLUSH, null);
}
}
public void onProviderEnabled(String provider) {
Log.i(TAG, locationType + ": is reliable");
//isreliable = true;
if (DEBUG_TTS) {
ContextExpandableListActivity.tts.speak("GPS reliability is " + String.valueOf(isreliable), TextToSpeech.QUEUE_FLUSH, null);
}
}
public void onStatusChanged(String provider, int status,
Bundle extras) {
switch (status) {
case LocationProvider.OUT_OF_SERVICE:
case LocationProvider.TEMPORARILY_UNAVAILABLE:
isreliable = false;
if (DEBUG_TTS) {
ContextExpandableListActivity.tts.speak("GPS reliability is " + String.valueOf(isreliable), TextToSpeech.QUEUE_FLUSH, null);
}
if (DEBUG) {
Log.i(TAG, "GPS Temporarily unavailable");
}
break;
case LocationProvider.AVAILABLE:
isreliable = true;
if (DEBUG_TTS) {
ContextExpandableListActivity.tts.speak("GPS reliability is " + String.valueOf(isreliable), TextToSpeech.QUEUE_FLUSH, null);
}
if (DEBUG) {
Log.i(TAG, "GPS Available");
}
break;
default:
if (DEBUG_TTS) {
ContextExpandableListActivity.tts.speak("Other GPS event detected", TextToSpeech.QUEUE_FLUSH, null);
}
if (DEBUG) {
Log.i(TAG, "GPS State unkown");
}
}
// TODO Check the status here to update isreliable
}
};
manager = (LocationManager) getSystemService(Context.LOCATION_SERVICE);
currentLocation = manager.getLastKnownLocation(locationType);
manager.requestLocationUpdates(locationType, 0, 0, listener);
IntentFilter restartFilter = new IntentFilter();
restartFilter.addAction(ContextConstants.CONTEXT_RESTART_INTENT);
registerReceiver(restartIntentReceiver, restartFilter);
running = true;
}
private void getPrefs() {
prefs = getSharedPreferences(ContextConstants.CONTEXT_PREFS, MODE_WORLD_READABLE);
// accelPoll = prefs.getInt(ContextConstants.PREFS_ACCEL_POLL_FREQ, 1);
// ignoreThreshold = prefs.getInt(ContextConstants.PREFS_ACCEL_IGNORE_THRESHOLD, 0);
prefs.registerOnSharedPreferenceChangeListener(this);
}
private void stopService() {
PreferenceManager.getDefaultSharedPreferences(this).unregisterOnSharedPreferenceChangeListener(this);
unregisterReceiver(restartIntentReceiver);
running = false;
}
BroadcastReceiver restartIntentReceiver = new BroadcastReceiver() {
public void onReceive(Context context, Intent intent) {
Log.d(TAG, TAG + "Restart Intent: " + intent.getAction());
if (running) {
stopService();
}
startService();
}
};
public int onStartCommand(Intent intent, int flags, int startId)
{
if (DEBUG) {
Log.i(TAG, "Service has been started");
}
return 0;
}
public void onDestroy()
{
stopService();
if (DEBUG) {
Log.i("GPS", "Stopping the service");
}
manager.removeUpdates(listener);
stopSelf();
}
@Override
public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) {
// if (key.equals(ContextConstants.PREFS_ACCEL_POLL_FREQ)) {
// Toast.makeText(this, "PREFS_ACCEL_POLL_FREQ", Toast.LENGTH_SHORT).show();
// getPrefs();
// stopService();
// startService();
// } else if (key.equals(ContextConstants.PREFS_ACCEL_IGNORE_THRESHOLD)) {
// Toast.makeText(this, "PREFS_ACCEL_IGNORE_THRESHOLD", Toast.LENGTH_SHORT).show();
// getPrefs();
// }
}
}